#pragma once
#include <cstdint>
#include <stdlib.h>
#include <thread>
#include <string>

#include <SFML\Network.hpp>

	struct ProtocolInfo {

		uint32_t PacketLength;

		uint16_t HeaderLength;

		uint16_t Version;

		uint32_t Action;

		uint32_t Parameter;
	};

	static ProtocolInfo* GetProtocolInfo(char* buffer, unsigned int size) {
		if (size < 16)
			return NULL;
		ProtocolInfo* _info = (ProtocolInfo*)malloc(sizeof(ProtocolInfo));
		_info->PacketLength = _byteswap_ulong(*reinterpret_cast<int32_t*>(buffer));
		_info->HeaderLength = _byteswap_ushort(*reinterpret_cast<int16_t*>(buffer + 4));
		_info->Version = _byteswap_ushort(*reinterpret_cast<int16_t*>(buffer + 6));
		_info->Action = _byteswap_ulong(*reinterpret_cast<int32_t*>(buffer + 8));
		_info->Parameter = _byteswap_ulong(*reinterpret_cast<int32_t*>(buffer + 12));

		return _info;
	}

	class CatClient
	{
	public:
		static CatClient* GetInstance();

		static void ReleaseInstance();
		
		void (*ReceivedEvt)(char * Danmaku);

		void (*DisconnectEvt)();

		void (*LogMessageEvt)(const char* format, ...);
		
		void SetClientPort(int _port);

		bool SendData(int action,char* data, unsigned int size);

	private:
		CatClient();

		~CatClient();
		//socket define
		const int SEND_BUF_SIZE = 64 * 1024;
		const int RECV_BUF_SIZE = 64 * 1024;

		//server define
		bool isConnected;

		sf::TcpSocket socket;

		int port = 0;

		void SendSocketDataAsync(int packetlength, short ver, int action, const char* body, unsigned int size);

		void ProcessData(int action, char* buffer, int size);

		void PrintMessage(std::string message);

		void _disconnect();
	};
